"""
全局异常处理器
统一处理各种异常并返回标准响应格式
"""

from fastapi import FastAPI, Request, HTTPException
from fastapi.exceptions import RequestValidationError
from starlette.exceptions import HTTPException as StarletteHTTPException
from starlette.responses import JSONResponse
from pydantic import ValidationError
import traceback

from app.utils.request import RequestHandler
from app.utils.app_log import logger


class GlobalExceptionHandler:
    """全局异常处理器类"""
    
    @staticmethod
    def setup_exception_handlers(app: FastAPI):
        """
        设置全局异常处理器
        
        Args:
            app: FastAPI应用实例
        """
        
        @app.exception_handler(HTTPException)
        async def http_exception_handler(request: Request, exc: HTTPException):
            """处理HTTPException"""
            logger.warning(f"HTTP Exception: {exc.status_code} - {exc.detail}")
            
            # 根据状态码返回相应的响应
            if exc.status_code == 401:
                return RequestHandler.unauthorized(
                    message=str(exc.detail),
                    remarks="请检查您的登录状态和权限"
                )
            elif exc.status_code == 403:
                return RequestHandler.forbidden(
                    message=str(exc.detail),
                    remarks="您没有权限访问此资源"
                )
            elif exc.status_code == 404:
                return RequestHandler.not_found(
                    message=str(exc.detail),
                    remarks="请检查请求的URL是否正确"
                )
            elif exc.status_code == 422:
                return RequestHandler.validation_error(
                    message=str(exc.detail),
                    remarks="请检查提交的数据格式"
                )
            else:
                return RequestHandler.error(
                    message=str(exc.detail),
                    code=exc.status_code,
                    remarks="请求处理失败"
                )
        
        @app.exception_handler(StarletteHTTPException)
        async def starlette_http_exception_handler(request: Request, exc: StarletteHTTPException):
            """处理Starlette HTTP异常"""
            logger.warning(f"Starlette HTTP Exception: {exc.status_code} - {exc.detail}")
            
            if exc.status_code == 404:
                return RequestHandler.not_found(
                    message="请求的资源不存在",
                    remarks=f"路径 {request.url.path} 未找到"
                )
            elif exc.status_code == 405:
                return RequestHandler.error(
                    message="请求方法不被允许",
                    code=405,
                    remarks=f"方法 {request.method} 不支持路径 {request.url.path}"
                )
            else:
                return RequestHandler.error(
                    message=str(exc.detail),
                    code=exc.status_code,
                    remarks="请求处理失败"
                )
        
        @app.exception_handler(RequestValidationError)
        async def validation_exception_handler(request: Request, exc: RequestValidationError):
            """处理请求验证错误"""
            logger.warning(f"Validation Error: {exc.errors()}")
            
            # 格式化验证错误信息
            error_details = []
            for error in exc.errors():
                field = " -> ".join(str(loc) for loc in error["loc"])
                message = error["msg"]
                error_details.append(f"{field}: {message}")
            
            return RequestHandler.validation_error(
                message="请求数据验证失败",
                errors=error_details,
                remarks="请检查提交的数据格式和必填字段"
            )
        
        @app.exception_handler(ValidationError)
        async def pydantic_validation_exception_handler(request: Request, exc: ValidationError):
            """处理Pydantic验证错误"""
            logger.warning(f"Pydantic Validation Error: {exc.errors()}")
            
            error_details = []
            for error in exc.errors():
                field = " -> ".join(str(loc) for loc in error["loc"])
                message = error["msg"]
                error_details.append(f"{field}: {message}")
            
            return RequestHandler.validation_error(
                message="数据模型验证失败",
                errors=error_details,
                remarks="请检查数据格式是否符合要求"
            )
        
        @app.exception_handler(ValueError)
        async def value_error_handler(request: Request, exc: ValueError):
            """处理值错误"""
            logger.error(f"Value Error: {str(exc)}")
            return RequestHandler.error(
                message="数据值错误",
                code=400,
                remarks=str(exc)
            )
        
        @app.exception_handler(KeyError)
        async def key_error_handler(request: Request, exc: KeyError):
            """处理键错误"""
            logger.error(f"Key Error: {str(exc)}")
            return RequestHandler.error(
                message="缺少必要的数据字段",
                code=400,
                remarks=f"缺少字段: {str(exc)}"
            )
        
        @app.exception_handler(Exception)
        async def general_exception_handler(request: Request, exc: Exception):
            """处理所有未捕获的异常"""
            logger.error(f"Unhandled Exception: {type(exc).__name__}: {str(exc)}")
            logger.error(f"Traceback: {traceback.format_exc()}")
            
            return RequestHandler.server_error(
                message="服务器内部错误",
                remarks="系统出现异常，请联系管理员"
            )


def setup_global_exception_handler(app: FastAPI):
    """
    设置全局异常处理器的便捷函数
    
    Args:
        app: FastAPI应用实例
    """
    GlobalExceptionHandler.setup_exception_handlers(app)